import User from "../../sql/module/user/user";
import Role from "../../sql/module/user/role";
import UserRole from "../../sql/module/_dictionaries/user_role";
import auth from "../../middlewares/auth";
import { ChangeInfoValidator, ChangePassSelfValidator, ChangeSelfInfoValidator, PageIndexValidator, RegisterValidator, UsersValidator } from "../../validators/user";
import { Forbbidend, NotFound, NotFoundItem, Repeatedly, Success } from "../../code/http-exception";
import { InfoValidator, ListValidator } from "../../validators/public";
import { Op } from "sequelize";
import Area from "../../sql/module/area/area";
import BlockNumber from "../../sql/module/area/block_number";
import RoomNumber from "../../sql/module/area/room_number";
import sequelize from "sequelize";
import log from "../../middlewares/log";
import UserUser from "../../sql/module/_dictionaries/user_user";
import Menu from "../../sql/module/menu";
import { LOGTYPE } from "../../lib/enum";

RoomNumber.hasMany(User);
User.belongsTo(RoomNumber);
Area.hasMany(User);
User.hasOne(UserUser);
UserUser.belongsTo(User, { foreignKey: 'linkUser' });
User.belongsTo(Area);
Role.belongsToMany(User, { through: UserRole });
User.belongsToMany(Role, { through: UserRole });

const router: Api = new Map()


//权限列表用于查询/筛选
router.set('/roleList', [auth('public'), async (ctx, next) => {
    const roles = await Role.findAll({ where: { id: { [Op.not]: 1 } }, attributes: ['id', 'uid', 'name'] })
    throw new Success(roles)
}])

//获取地区，设置可流转账号
router.set('/roomNumberList', [auth('changeLink'), async (ctx, next) => {
    const { rows, count } = await Area.findAndCountAll({
        attributes: ['name', 'id'],
        include: {
            model: BlockNumber, as: 'children', attributes: ['name', 'id'],
            //@ts-ignore
            include: { model: RoomNumber, as: 'children', attributes: ['name', 'id'] }
        }
    })
    throw new Success({ list: rows, total: count })
}])
//用于账号列表地区查询
router.set('/areas', [auth('userList'), async (ctx, next) => {
    const area = await Area.findAll({
        attributes: { exclude: ['createdAt', 'updatedAt'] }
    })
    throw new Success(area)
}])
//管理员获取房间号用于创建账号
router.set('/roomNumbers', [auth(['addUser1', 'addUser2']), async (ctx, next) => {
    const AreaId = ctx.auth.AreaId
    if (AreaId) {
        const area = await BlockNumber.findAll({
            attributes: { exclude: ['createdAt', 'updatedAt'] },
            where: { AreaId },
            include: {
                model: RoomNumber,
                attributes: ['name', 'id'],
                as: 'children',
            },
        })
        throw new Success(area)
    } else {
        const area = await Area.findAll({
            attributes: { exclude: ['createdAt', 'updatedAt'] },
            include: {
                model: BlockNumber,
                attributes: ['name', 'id'],
                as: 'children',
                include: [{ model: RoomNumber, as: 'children', attributes: ['name', 'id'] }]
            },
        })
        throw new Success(area)
    }
}])
//注册添加
router.set('/register', [auth(['addUser1', 'addUser2']), async (ctx, next) => {
    const v = await new RegisterValidator().validate(ctx)
    const RoomNumberId = v.get('body.RoomNumberId')
    const location = v.get('body.location')
    const roles = v.get('body.roles')
    const point = location ? { type: 'Point', coordinates: [location.x, location.y] } : null
    let areas: { AreaId?: number, BlockNumberId?: number, RoomNumber_name?: string, Area_name?: string, BlockNumber_name?: string } = {}
    if (RoomNumberId) {
        const room = await RoomNumber.findOne({
            attributes: [['id', 'RoomNumberId'], [sequelize.col('BlockNumber.id'), 'BlockNumberId'],
            [sequelize.col('Area.id'), 'AreaId'],
            [sequelize.col('BlockNumber.name'), 'BlockNumber_name'], ['name', 'RoomNumber_name'],
            [sequelize.col('Area.name'), 'Area_name']
            ],
            where: { id: RoomNumberId },
            //@ts-ignore
            include: [Area, BlockNumber]
        })
        if (!room) throw new NotFoundItem('地区不存在')
        areas = room?.dataValues
    }
    if (roles.includes(1)) throw new Forbbidend()
    const user = await User.create({
        phone: v.get('body.phone'),
        nickname: v.get('body.nickname'),
        avatar: v.get('body.avatar'),
        RoomNumberId,
        ...areas,
        location: point,
        password1: '123456'
    })
    ctx.nickname = user.dataValues.nickname
    await UserRole.bulkCreate(roles.map((item: any) => ({
        RoleId: item,
        UserId: user.id
    })))
    await next()
    throw new Success('请求成功', 20000)
}, log((ctx) => '注册了一个为' + ctx.nickname + '的账号', "/api/v1/user/delete", "create")])

//管理员修改详情
router.set('/changeInfo', [auth(['userDetail1', 'userDetail2']), async (ctx, next) => {
    const v = await new ChangeInfoValidator().validate(ctx)
    const id = v.get('query.id')
    const RoomNumberId = v.get('body.RoomNumberId')
    const roles = v.get('body.roles')
    const AreaId = ctx.auth.AreaId
    const location = v.get('body.location')
    let areas: { AreaId?: number, BlockNumberId?: number, RoomNumber_name?: string, Area_name?: string, BlockNumber_name?: string } = {}
    if (RoomNumberId) {
        const room = await RoomNumber.findOne({
            attributes: [['id', 'RoomNumberId'], [sequelize.col('BlockNumber.id'), 'BlockNumberId'],
            [sequelize.col('Area.id'), 'AreaId'],
            [sequelize.col('BlockNumber.name'), 'BlockNumber_name'],
            ['name', 'RoomNumber_name'],
            [sequelize.col('Area.name'), 'Area_name']
            ],
            where: { id: RoomNumberId },
            include: [Area, BlockNumber]
        })
        areas = room?.dataValues
    }
    if (roles.includes(1)) throw new Forbbidend()
    const point = location ? { type: 'Point', coordinates: [location.x, location.y] } : null
    ctx.from = await User.findOne({ where: { id }, include: { model: Role, attributes: ['name', 'id'] } })
    const user = await User.findOne({ where: { id } })
    if (!user) throw new NotFound()
    await user.update({
        phone: v.get('body.phone'),
        nickname: v.get('body.nickname'),
        avatar: v.get('body.avatar'),
        AreaId, location: point,
        RoomNumberId,
        ...areas
    })
    await UserRole.destroy({ where: { UserId: id } })
    await UserRole.bulkCreate(roles.map((item: any) => ({
        RoleId: item,
        UserId: id
    })))
    ctx.to = await User.findOne({ where: { id }, include: { model: Role, attributes: ['name', 'id'] } })
    await next()
    throw new Success('请求成功', 20000)
}, log((ctx) => '修改了' + ctx.from.dataValues.nickname + '的详情', "/api/v1/user/recoverInfo", "update")])

router.set('/userList', [auth('userList'), async (ctx) => {
    const v = await new ListValidator().validate(ctx)
    const limit = v.get('query.limit')
    const page_index = v.get('query.page_index')
    const uid = v.get('body.uid')
    const nickname = v.get('body.nickname')
    const AreaId = ctx.auth.AreaId || v.get('body.Area_name')
    const id = ctx.auth.id
    let roleSearch: any = undefined
    const search_key: any = {
        id: { [Op.not]: id }
    }
    nickname && (search_key.nickname = { [Op.substring]: nickname })
    AreaId && (search_key.AreaId = AreaId)
    typeof uid === "number" && (roleSearch = { uid })
    const { rows, count } = await User.findAndCountAll({
        attributes: { exclude: ['token', 'password1', 'updatedAt', 'deletedAt', 'pageIndex'] },
        where: search_key,
        include: [{ model: Role, where: roleSearch }],
        distinct: true,
        limit: limit * 1,
        offset: (page_index - 1) * limit
    })
    throw new Success({ list: rows, total: count })
}])

//用户获取详情
router.set('/getSelfInfo', [auth('public'), async (ctx, next) => {
    const use = await User.findOne({
        attributes: {
            exclude: ['password1', 'token', 'deletedAt', 'createdAt']
        },
        where: {
            id: ctx.auth.id
        },
        include: [
            { model: Role, attributes: { exclude: ['createdAt', 'updatedAt', 'deletedAt'] }, through: { attributes: [] } }
        ]
    })
    throw new Success(use, 20000)
}])

//管理员获取详情
router.set('/getInfo', [auth(['userDetail1', 'userDetail2']), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')
    const AreaId = ctx.auth.AreaId
    const where: any = { id }
    AreaId && (where.AreaId = AreaId)
    const user = await User.findOne({
        attributes: {
            exclude: ['password1', 'token', 'deletedAt', 'createdAt', 'updatedAt']
        },
        where,
        include: [
            { model: Role, attributes: { exclude: ['createdAt', 'updatedAt', 'deletedAt'] } }],
    })
    if (!user) throw new NotFound()
    throw new Success(user, 20000)
}])

//管理员删除账号
router.set('/delete', [auth('deleteUser'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')
    const AreaId = ctx.auth.AreaId
    const where: any = { id }
    AreaId && (where.AreaId = AreaId)
    const user = await User.findOne({
        where
    })
    if (!user) throw new NotFound()
    const { nickname, phone } = user?.dataValues
    ctx.nickname = nickname
    ctx._id = id
    await user.update({
        phone: '-' + phone
    })
    await user.destroy()
    await next()
    throw new Success('删除成功', 20000)
}, log((ctx) => '删除了账号' + ctx.nickname, '/api/v1/user/recover', 'delete')])

//用户修改密码
router.set('/changeSelfPassword', [auth('public'), async (ctx, next) => {
    const v = await new ChangePassSelfValidator().validate(ctx)
    const from = await User.verifyEmailPassword(ctx.auth.scope, v.get('body.password'))
    await from?.update({ password1: v.get('body.password1') })
    throw new Success('请求成功', 20000)
}])

//用户修改详情
router.set('/changeSelfInfo', [auth('public'), async (ctx, next) => {
    const v = await new ChangeSelfInfoValidator().validate(ctx)
    const user = await User.findOne({
        where: {
            id: ctx.auth.id
        }
    })
    if (!user) { throw new NotFound() }
    await user.update({
        phone: v.get('body.phone'),
        nickname: v.get('body.nickname'),
        avatar: v.get('body.avatar')
    })
    throw new Success('请求成功', 20000)
}])

//用户注册权限默认visitor
router.set('/register_self', async (ctx, next) => {
    const v = await new RegisterValidator().validate(ctx)
    const user = await User.create({
        phone: v.get('body.phone'),
        password1: v.get('body.password1'),
        nickname: v.get('body.nickname'),
        avatar: v.get('body.avatar')
    })
    await UserRole.create({
        RoleId: 2,
        UserId: user.id
    })
    throw new Success('请求成功', 20000)
})

//管理员重置账号密码
router.set('/resetPassword', [auth('resetPassword'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')
    const AreaId = ctx.auth.AreaId
    const where: any = { id }
    AreaId && (where.AreaId = AreaId)
    await User.update({
        password1: '123456'
    }, { where })
    throw new Success()
}])

//查看所有main和user的账号，用于设置可流转账号
router.set('/users', [auth('changeLink'), async (ctx, next) => {
    const v = await new UsersValidator().validate(ctx)
    const limit = v.get('query.limit')
    const page_index = v.get('query.page_index')
    const RoomNumberId = v.get('body.RoomNumberId')
    const id = ctx.auth.id
    const { rows, count } = await User.findAndCountAll({
        attributes: ['id', 'nickname', 'phone', 'avatar', 'fullUrl'],
        where: {
            id: { [Op.not]: id },
            RoomNumberId
        },
        include: {
            model: Role, attributes: ['name'], through: { attributes: [] }
        },
        limit: limit * 1,
        offset: (page_index - 1) * limit
    })
    throw new Success({ list: rows, total: count })
}])

//获取可流转账号
router.set('/links', [auth('changeLink'), async (ctx, next) => {
    const id = ctx.auth.id
    const rows = await UserUser.findAll({
        where: {
            UserId: id
        },
        include: { model: User, attributes: ['nickname'] }
    })
    throw new Success({ list: rows })
}])

//添加可流转账号
router.set('/addLink', [auth('changeLink'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const linkUser = v.get('query.id')
    const UserId = ctx.auth.id
    const data = { UserId, linkUser }
    const redata = { UserId: linkUser, linkUser: UserId }
    const user_user = await UserUser.findOne({
        where: data
    })
    if (user_user) throw new Repeatedly('已存在该账号')
    await UserUser.create(data)
    await UserUser.findOrCreate({ where: redata, defaults: redata })
    throw new Success()
}])

//移除可流转账号
router.set('/removeLink', [auth('changeLink'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')
    const UserId = ctx.auth.id
    await UserUser.destroy({
        where: {
            UserId,
            id
        }
    })
    throw new Success()
}])
//自定义首页
router.set('/setPageIndex', [auth('public'), async (ctx, next) => {
    const v = await new PageIndexValidator().validate(ctx)
    const id = ctx.auth.id
    await User.update({
        pageIndex: v.get('body.url')
    }, { where: { id } })
    throw new Success()
}])

//获取全部页面类型的菜单
router.set('/menus_page', [auth('public'), async (ctx, next) => {
    const menus = await Menu.findAll({
        attributes: ['url', 'label'],
        where: {
            type: 2,
            ['$Roles.uid$']: ctx.auth.uids
        },
        include: { model: Role, attributes: [] }
    })
    throw new Success(menus)
}])

//管理员恢复账号
router.set('/recover', [auth('resetRecord'), async ctx => {
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')

    await User.restore({
        where: {
            id
        }
    })
    const user = await User.findOne({
        where: {
            id
        }
    })
    if (!user) throw new NotFoundItem()
    try {
        await user.update({
            phone: user.phone.replaceAll('-', '')
        })
    } catch (err) {
        throw new Success('手机号被占用，请及时修改', 20001)
    }
    throw new Success('恢复成功', 20000)
}])

//恢复账号信息
router.set('/recoverInfo', [auth('resetRecord'), async ctx => {
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')
    const dff = JSON.parse(v.get('body.dff'))
    if (dff.Roles.length > 0) {
        await UserRole.destroy({ where: { UserId: id } })
        await UserRole.bulkCreate(dff.Roles
            .filter((item: any) => item.type !== LOGTYPE.add).map((item: any) => ({
                RoleId: item.id,
                UserId: id
            })))
    }
    delete dff.Menus
    const user = await User.findOne({
        where: {
            id
        }
    })
    if (!user) throw new NotFoundItem()
    await user.update(dff)
    throw new Success()
}])

export { router }